﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace WindowsFormsApp2
{
    static class SteamCodeGenerator
    {
        private static char[] steamGuardCodeTranslations = "23456789BCDFGHJKMNPQRTVWXY".ToCharArray();
        public static String generateSteamGuardCode(long time, String shared_secret)
        {
            byte[] sharedSecretArray = getBase64(shared_secret);
            if (shared_secret != null)
            {
                time /= 30;
                byte[] timeArray = new byte[8];
                for (int i = 8; i > 0; i--)
                {
                    timeArray[i - 1] = (byte)(int)time;
                    time = RightMove(time, 8);
                }
                try
                {
                    byte[] hmac_result = getHmacsha1(sharedSecretArray, timeArray);
                    char[] codeArray = new char[5];
                    int offset = hmac_result[19] & 15;
                    int bin_code = (hmac_result[offset] & 127) << 24 | (hmac_result[offset + 1] & 255) << 16
                            | (hmac_result[offset + 2] & 255) << 8 | hmac_result[offset + 3] & 255;
                    for (int i = 0; i < 5; i++)
                    {
                        codeArray[i] = steamGuardCodeTranslations[bin_code % steamGuardCodeTranslations.Length];
                        bin_code /= steamGuardCodeTranslations.Length;
                    }
                    return new String(codeArray);
                }
                catch (Exception){}
            }
            return "未获取到";
        }
        public static byte[] getBase64(String s)
        {
            byte[] data=null;
            try
            {
                //data = System.Text.Encoding.UTF8.GetBytes(s);
                data = Convert.FromBase64String(s);
            }
            catch (Exception){}
            return data;
        }
        public static long RightMove(long value, int pos)
        {
            //移动 0 位时直接返回原值
            if (pos != 0)
            {
                // int.MaxValue = 0x7FFFFFFF 整数最大值
                int mask = int.MaxValue;
                //无符号整数最高位不表示正负但操作数还是有符号的，有符号数右移1位，正数时高位补0，负数时高位补1
                value = value >> 1;
                //和整数最大值进行逻辑与运算，运算后的结果为忽略表示正负值的最高位
                value = value & mask;
                //逻辑运算后的值无符号，对无符号的值直接做右移运算，计算剩下的位
                value = value >> pos - 1;
            }

            return value;
        }
        public static byte[] getHmacsha1(byte[] key, byte[] value)
        {
            HMACSHA1 mac = new HMACSHA1();
            mac.Key = key;
            return mac.ComputeHash(value);
        }
    }
}
